<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="formRules"
    :label-width="formConfig.labelWidth || 'auto'"
    :label-position="formConfig.labelPosition || 'right'"
    label-suffix="："
    :style="{ width: formConfig.width }"
    :validateOnRuleChange="formConfig.validateOnRuleChange"
  >
    <input type="text" name="notautosubmit" style="display: none" />
    <el-row>
      <el-col :span="field.row" v-for="field in formFields" :key="field.prop">
        <bTitle
          v-if="field.components == 'title'"
          :title="field.label"
          :class="field.class"
          :style="field.style"
        ></bTitle>
        <el-form-item
          v-else
          :label="field.label"
          :prop="field.prop"
          :class="'el-col-' + field.span"
        >
          <template v-if="$slots[field.prop]">
            <slot :name="field.prop"></slot>
          </template>
          <span
            class="is-disabled"
            v-else-if="
              ['input', 'inputNumber', 'textarea'].includes(field.components) &&
              field.disabled
            "
            >{{ formData[field.prop] }}{{ field.append }}</span
          >
          <el-input-number
            v-else-if="field.components === 'inputNumber'"
            v-model="formData[field.prop]"
            :min="field.min"
            :max="field.max"
            :step="field.step"
            :placeholder="placeholder(field)"
            :precision="field.precision"
            :controls="field.controls"
            :disabled="field.disabled"
            @change="field.onChange"
            clearable
          ></el-input-number>
          <el-input
            :id="field.prop"
            v-else-if="field.components == 'input' && field.type == 'number'"
            :type="field.type"
            v-model.number="formData[field.prop]"
            :placeholder="placeholder(field)"
            clearable
            :maxlength="field.maxlength"
            :disabled="field.disabled"
            @change="field.onChange"
          >
            <template slot="append" v-if="field.append">{{
              field.append
            }}</template>
          </el-input>
          <el-input
            :id="field.prop"
            v-else-if="['input', 'textarea'].includes(field.components)"
            :type="field.type"
            v-model="formData[field.prop]"
            :placeholder="placeholder(field)"
            :maxlength="field.maxlength"
            clearable
            :disabled="field.disabled"
            @change="field.onChange"
            :readonly="field.readonly"
            :rows="field.rows"
            resize="none"
          >
            <template slot="append" v-if="field.append">{{
              field.append
            }}</template>
          </el-input>
          <bSelect
            :id="field.prop"
            v-else-if="field.components === 'select'"
            :config="field"
            v-model.lazy="formData[field.prop]"
            @change="field.onChange"
            clearable
            filterable
            @optionsChange="field.optionsChange"
          >
          </bSelect>
          <el-radio-group
            :id="field.prop"
            v-else-if="field.components === 'radioButton'"
            v-model="formData[field.prop]"
            @change="field.onChange"
            :disabled="field.disabled"
          >
            <el-radio-button
              :label="item.value"
              v-for="item in field.options"
              :key="item.value"
              :disabled="item.disabled"
              >{{ item.label }}</el-radio-button
            >
          </el-radio-group>
          <el-radio-group
            :id="field.prop"
            v-else-if="field.components === 'radioGroup'"
            v-model="formData[field.prop]"
            @change="field.onChange"
            :disabled="field.disabled"
          >
            <el-radio
              :label="item.value"
              v-for="item in field.options"
              :key="item.value"
              >{{ item.label }}</el-radio
            >
          </el-radio-group>
          <el-checkbox-group
            :id="field.prop"
            v-else-if="field.components === 'checkbox'"
            v-model="formData[field.prop]"
            @change="field.onChange"
            :disabled="field.disabled"
          >
            <el-checkbox
              v-for="item in field.options"
              :label="item.value"
              :key="item.value"
              >{{ item.label }}</el-checkbox
            >
          </el-checkbox-group>
          <el-date-picker
            :id="field.prop"
            v-else-if="field.components == 'date'"
            :type="field.type"
            clearable
            v-model="formData[field.prop]"
            :placeholder="placeholder(field)"
            :disabled="field.disabled"
            @change="field.onChange"
            :format="field.format"
            :value-format="field.valueFormat"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :default-time="field.defaultTime"
          />
          <file-upload
            :id="field.prop"
            v-else-if="field.components === 'uploadFile'"
            v-model="formData[field.prop]"
            :disabled="field.disabled"
            clearable
          />
          <span :id="field.prop" v-else>{{ formData[field.prop] }}</span>
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item v-if="formButtons.length > 0" class="b-form-button-group">
      <el-button
        v-for="btn in formButtons"
        :ref="btn.key"
        :key="btn.key"
        :type="btn.type"
        :icon="btn.icon"
        :size="btn.size"
        @click="onClick(btn)"
        :loading="btn.loading"
        >{{ btn.label }}</el-button
      >
    </el-form-item>
  </el-form>
</template>

<script>
import FileUpload from "@/components/FileUpload";
import bTitle from "@/components/bTitle";
import bSelect from "@/components/bSelect";
import { componentPlaceholder } from "@/utils/index";
import { getUser } from "@/utils/auth";
export default {
  components: {
    FileUpload,
    bTitle,
    bSelect,
  },
  props: {
    config: {
      type: Object,
      default: () => ({}),
    },
    model: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      formData: {},
      buttonGroup: {
        submit: {
          label: "保存",
          type: "primary",
          validate: true,
        },
        cancel: {
          label: "取消",
          type: "default",
        },
      },
    };
  },
  watch: {
    model: {
      handler(val) {
        if (this.config?.fields?.areaId) {
          let areaId = getUser()?.areaId ?? "";
          if (areaId && !val.areaId) {
            val.areaId = areaId;
          }
        }
        this.formData = val;
        setTimeout(() => {
          this.$refs?.formRef?.clearValidate();
        }, 0);
      },
      immediate: true,
      deep: true,
    },
    formData: {
      handler(val) {
        this.$emit("update:model", val);
      },
      deep: true,
    },
  },
  computed: {
    formConfig() {
      const config = this.config || {};
      config.width = config.width || "100%";
      return config;
    },
    formFields() {
      let arr = [];
      for (const key in this.config?.fields) {
        let field = this.config?.fields[key];
        if (field.hide) continue;
        field.prop = key;
        field.row = field.row || 24;
        field.span = field.span || 24;
        if (field.components == "date") {
          if (field.type == "daterange") {
            this.$set(
              this.formData,
              field.prop,
              this.formData[field.prop] ?? []
            );
            field.defaultTime = field.defaultTime ?? ["00:00:00", "23:59:59"];
          } else {
            field.defaultTime = field.defaultTime ?? undefined;
          }
        }
        if (field.components == "inputNumber") {
          field.precision = field.precision ?? 2;
          field.controls = field.controls ?? false;
        }
        if (field.components === "select") {
          field.optionsChange =
            field.optionsChange && field.optionsChange instanceof Function
              ? field.optionsChange
              : () => {};
        }
        if (
          this.config.visible &&
          field.options &&
          field.options instanceof Function
        ) {
          field.options().then((res) => (field.options = res));
          field.options = [];
        }
        field.onChange =
          field.onChange && field.onChange instanceof Function
            ? field.onChange
            : () => {};
        field.valueFormat =
          field.valueFormat ||
          (field.components == "date" ? "yyyy-MM-dd HH:mm:ss" : undefined);
        if (field.components == "title") {
          field.row = 24;
        }
        field.rows = field.rows || 2;
        field.disabled =
          field.disabled !== undefined ? field.disabled : this.config.readonly;
        arr.push(field);
      }
      return arr;
    },
    formRules() {
      let rules = {};
      for (const key in this.config?.fields) {
        let field = this.config?.fields[key];
        rules[key] = this.config?.rules?.[key] || [];
        if (field.required && !this.config.readonly) {
          rules[key].unshift({
            required: true,
            message: `${
              field.placeholder ??
              componentPlaceholder(field.components) + field.label
            }`,
            trigger:
              componentPlaceholder(field.components) == "请填写"
                ? "blur"
                : "change",
          });
        }
        if (field.min !== undefined && field.max !== undefined) {
          rules[key].push({
            type: "number",
            min: field.min,
            max: field.max,
            message: `${field.label}值在${field.min}到${field.max}之间`,
            trigger: "blur",
          });
        } else if (field.min !== undefined) {
          rules[key].push({
            type: "number",
            min: field.min,
            message: `${field.label}不能小于${field.min}`,
            trigger: "blur",
          });
        } else if (field.max !== undefined) {
          rules[key].push({
            type: "number",
            max: field.max,
            message: `${field.label}不能大于${field.max}`,
            trigger: "blur",
          });
        }
        if (field.rules) {
          rules[key] = [...rules[key], ...field.rules];
        }
        if (rules[key].length == 0) delete rules[key];
      }
      return rules;
    },
    formButtons() {
      let arr = [];
      for (const key in this.config.button) {
        let obj = this.config.button[key];
        let btn = this.buttonGroup[key];
        arr.push({ ...btn, ...obj, key });
      }
      return arr;
    },
  },
  methods: {
    placeholder(field) {
      if (this.config.readonly || field.disabled) return "-";
      return (
        field.placeholder ||
        componentPlaceholder(field.components) + field.label
      );
    },
    validate() {
      return new Promise((resolve, reject) => {
        this.$refs.formRef
          .validate()
          .then(() => {
            resolve(this.formData);
          })
          .catch(() => {
            reject();
          });
      });
    },
    onClick(btn) {
      if (btn.validate) {
        this.validate()
          .then(() => {
            btn.onClick && btn.onClick(this.formData);
          })
          .catch(() => {});
      } else {
        btn.onClick && btn.onClick();
      }
    },
    resetFields() {
      this.$refs.formRef.resetFields();
    },
    clearValidate() {
      this.$refs.formRef.clearValidate();
    },
  },
};
</script>

<style lang="scss" scoped>
.el-form {
  :deep(.el-row) {
    display: flex;
    flex-wrap: wrap;
    .el-col:has(.is-disabled),
    .el-col:has(.upload-file.disabled) {
      .el-form-item {
        margin-bottom: 0;
        .el-form-item__label {
          &::before {
            display: none;
          }
        }
      }
      & + .el-col-24:not(:has(.is-disabled,.upload-file.disabled)) {
        margin-top: 12px;
      }
    }
    .is-disabled {
      input {
        // padding: 0 15px;
        // background-color: #f2f3f5;
        // border-color: #b1b1b1;
        background-color: transparent;
        border-color: transparent;
        color: #333;
        padding: 0;
      }

      textarea {
        // background-color: #f2f3f5;
        // border-color: #b1b1b1;
        background-color: transparent;
        border-color: transparent;
        color: #333;
      }
      .el-input__suffix,
      .el-input__prefix {
        display: none;
      }
      .el-input__inner {
        &:hover {
          border-color: transparent;
        }
      }
      .el-input-group__append {
        background-color: transparent;
        border-color: transparent;
      }
    }

    .el-input-number {
      width: 100%;

      input {
        text-align: left;
      }
    }

    .el-radio {
      color: #333;
    }

    // .el-input__inner:read-only{
    //     background-color: #ccc;
    // }

    .upload-file {
      &.disabled {
        .upload-file-uploader {
          display: none;
        }

        .el-upload-list__item {
          border: none;

          .ele-upload-list__item-content-action {
            display: none;
          }
        }
      }
    }
  }
}
</style>
